package com.vcredit.creditcat.manager;

import com.fasterxml.jackson.core.type.TypeReference;
import com.vcredit.creditcat.dto.authpersonalinfo.CompanyInfo;
import com.vcredit.creditcat.enumtype.*;
import com.vcredit.creditcat.model.*;
import com.vcredit.creditcat.service.*;
import com.vcredit.framework.annotation.Log;
import com.vcredit.framework.util.JacksonUtil;
import org.apache.commons.beanutils.BeanUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.dubbo.config.annotation.Service;
import com.vcredit.creditcat.api.IAuthPersonalInfoManager;
import com.vcredit.creditcat.dto.authpersonalinfo.AuthPersonalInfoDto;
import com.vcredit.creditcat.exception.BasicInfoException;
import com.vcredit.creditcat.service.product.util.EnumExtUtil;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.lang.reflect.Method;
import java.util.*;

@Service(protocol = {"protocol1"}, version = "1.0")
public class AuthPersonalInfoManager implements IAuthPersonalInfoManager {

  @Autowired
  private AuthPersonalInfoService personalInfoService;

  @Autowired
  private CreditCatProcessManager creditCatProcessManager;
  @Autowired
  private AuthLogService authLogService;
  @Autowired
  private AuthPersonalAddressService authPersonalAddressService;
  @Autowired
  private SysNationService sysNationService;
  @Autowired
  private CustSupplementItemService custSupplementItemService;

  @Override
  public void insert(AuthPersonalInfoDto param, Cust cust) throws Exception {
    AuthPersonalInfo originalInfo = personalInfoService.findByProcessId(cust.getLastProccessId());
    /*if (null != originalInfo) {
      throw new BasicInfoException("该用户基本信息已经存在");
    }*/

  
    String marriageValue = EnumExtUtil.getEnumOnValue(AuthMarriageEnum.class, String.valueOf(param.getMarriage()), "code").getDesc();
    String educationValue = EnumExtUtil.getEnumOnValue(AuthEducationEnum.class, String.valueOf(param.getEducation()), "code").getDesc();
    String incomeValue = EnumExtUtil.getEnumOnValue(AuthMonthlyIncomeEnum.class, String.valueOf(param.getMonthlyIncome()), "code").getDesc();
    String professionValue = EnumExtUtil.getEnumOnValue(ProfessionTypeEnum.class, String.valueOf(param.getProfessionType()), "code").getDesc();
    
    AuthPersonalInfo authInfo = new AuthPersonalInfo(
            cust.getCustId(),
            cust.getLastProccessId(),
            param.getEducation(),
            educationValue,
            param.getMonthlyIncome(),
            incomeValue,
            param.getMarriage(),
            marriageValue,
            param.getProfessionType(),
            professionValue,
            null,null,
            param.geteMailAddress(),
            param.getIsProvidentFund(),
            param.getCensusIsLiveCity());
    if(null == originalInfo){
    	 personalInfoService.insert(authInfo);
    }else{
    	 authInfo.setPersonalInfoId(originalInfo.getPersonalInfoId());
    	 personalInfoService.update(authInfo);
    }
   
    //保存地址和公司信息
    CompanyInfo companyInfo=param.getCompanyInfo();
    AuthPersonalAddress personalAddress=new AuthPersonalAddress();
    personalAddress.setCustId(cust.getCustId());
    personalAddress.setProcessId(cust.getLastProccessId());
    personalAddress.setAddressName(companyInfo.getCompanyName());
    personalAddress.setAddressType(0);
    personalAddress.setAddress(companyInfo.getAddress());
    personalAddress.setRoad(companyInfo.getAddress());
    personalAddress.setPhone(companyInfo.getCompanyTel());
    String[] codes=companyInfo.getAreaCode().split("-");
    if (codes.length==3){
      SysNation province=sysNationService.findByCode(codes[0]);
      if (province!=null){
        personalAddress.setProvince(province.getProvince());
        personalAddress.setProvinceCode(province.getCode());
      }
      SysNation city=sysNationService.findByCode(codes[1]);
      if (city!=null){
        personalAddress.setCity(city.getCity());
        personalAddress.setCityCode(city.getCode());
      }
      SysNation district=sysNationService.findByCode(codes[2]);
      if (district!=null){
        personalAddress.setZone(district.getDistrict());
        personalAddress.setZoneCode(district.getCode());
      }
    }
    Location location=param.getLocation();
    if(location!=null){
      personalAddress.setGeoAddress(location.getCityAddress());
      personalAddress.setGeoCity(location.getCityName());
      personalAddress.setGeoZone(location.getDistinct());
      personalAddress.setGeoLatitude(location.getLatitude());
      personalAddress.setGeoLongitude(location.getLongitude());
      personalAddress.setGeoRoad(location.getRoad());
      personalAddress.setIp(location.getIp());
    }
    List<AuthPersonalAddress> addressOldList = authPersonalAddressService.findByCustId(cust.getCustId(),0);
    if(addressOldList.size()>0){//如果已经存在家庭地址记录，则更新
      for(AuthPersonalAddress authPersonalAddress:addressOldList) {
        personalAddress.setAddressId(authPersonalAddress.getAddressId());
        authPersonalAddressService.update(personalAddress);
      }
    }else {
      authPersonalAddressService.insert(personalAddress);
    }
    // 客户实名认证操作
    creditCatProcessManager.itemDone(new AuthItem(AuthItemEnum.BASE_INFO.getCode()),
            cust.getLastProccessId());
    authLogService.insert(new AuthLog(cust.getLastProccessId(), cust.getCustId(), AuthItemEnum.BASE_INFO.getCode(),
            "", new Date()));
  }

  /**
   * 初始化用户基本信息
   * @param cust
   * @param authCode
   * @return
   * @throws Exception
   */
  @Override
  public Map<String,Object> getPersonalInfo(Cust cust,String authCode) throws Exception{
    PersonalInfoUnion personalInfoUnion=getPersonalInfoUnion(cust);
    List<String> columns=new ArrayList<>();
    Element elementColumns=getRootElement("classpath:/config/basicInfoColumnsByItemId.xml");
    for(Iterator i = elementColumns.elementIterator(); i.hasNext();) {
      Element item = (Element) i.next();
      if(authCode.equals(item.attribute("authCode").getText())) {
        for (Iterator j = item.elementIterator(); j.hasNext(); ) {
          Element node = (Element) j.next();
          columns.add(node.getText());
        }
      }
    }
    List<Map<String,Object>> list=new ArrayList<>();
    for(String column:columns){
      Element element=getRootElement("classpath:/config/personalInfoUnionColumns.xml");
      for(Iterator i = element.elementIterator(); i.hasNext();) {
        Map<String,Object> map=new LinkedHashMap<>();
        Element basicColumn = (Element) i.next();
        String columnName=basicColumn.attribute("property").getText();
        if(columnName.equals(column)) {
          map.put("name", columnName);
          Class unionClass = PersonalInfoUnion.class;
          StringBuilder stringBuilder=new StringBuilder();
          stringBuilder=stringBuilder.append("get").append(columnName.substring(0, 1).toUpperCase()).append(columnName.substring(1));
          Method method=unionClass.getMethod(stringBuilder.toString(),null);
          Object value=method.invoke(personalInfoUnion);
          if(value == null) value ="";
          map.put("value", value.toString());
          for (Iterator j = basicColumn.elementIterator(); j.hasNext(); ) {
            Element node = (Element) j.next();
            String name = node.getQName().getName();
            String text = node.getText();
            Object  content= text;
            if ("items".equals(name) && org.apache.commons.lang.StringUtils.isNotBlank(text)) {
              content= JacksonUtil.Json2Obj(text,new TypeReference<Object>(){});
            }
            map.put(name, content);
          }
          list.add(map);
        }
      }
    }
    Map<String,Object> result=new HashMap();
    result.put("basicInfo",list);
    return result;
  }

  /**
   * 保存基本信息
   * @param cust
   * @param param
   * @throws Exception
   */
  @Override
  @Log
  @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  public void savePersonalInfo(Long productId,Cust cust,Map<String,Object> param) throws Exception{
    PersonalInfoUnion personalInfoUnion=setPersonalInfoUnion(param);
    if(personalInfoUnion.getEducationKey()!=null){
      String educationValue = EnumExtUtil.getEnumOnValue(AuthEducationEnum.class, String.valueOf(personalInfoUnion.getEducationKey()), "code").getDesc();
      personalInfoUnion.setEducationValue(educationValue);
    }
    if(personalInfoUnion.getMarriageKey()!=null){
      String marriageValue = EnumExtUtil.getEnumOnValue(AuthMarriageEnum.class, String.valueOf(personalInfoUnion.getMarriageKey()), "code").getDesc();
      personalInfoUnion.setMarriageValue(marriageValue);
    }
    if(personalInfoUnion.getSalaryKey()!=null){
      String salaryValue = EnumExtUtil.getEnumOnValue(AuthMonthlyIncomeEnum.class, String.valueOf(personalInfoUnion.getSalaryKey()), "code").getDesc();
      personalInfoUnion.setSalaryValue(salaryValue);
    }
    if(personalInfoUnion.getProfessionKey()!=null){
      String professionValue = EnumExtUtil.getEnumOnValue(ProfessionTypeEnum.class, String.valueOf(personalInfoUnion.getProfessionKey()), "code").getDesc();
      personalInfoUnion.setProfessionValue(professionValue);
    }
    if(personalInfoUnion.getIndustryKey()!=null){
      String industryValue=EnumExtUtil.getEnumOnValue(IndustryTypeEnum.class, String.valueOf(personalInfoUnion.getIndustryKey()), "code").getDesc();
      personalInfoUnion.setIndustryValue(industryValue);
    }
    if(personalInfoUnion.getPersonalInfoId()==null){
		AuthPersonalInfo oldAuthPersonalInfo=personalInfoService.findByProcessId(cust.getLastProccessId());
		if(oldAuthPersonalInfo!=null){
			personalInfoUnion.setPersonalInfoId(oldAuthPersonalInfo.getPersonalInfoId());
			personalInfoService.update(personalInfoUnion);
		}else{
			personalInfoUnion.setCustId(cust.getCustId());
			personalInfoUnion.setProccessId(cust.getLastProccessId());
			personalInfoService.insert(personalInfoUnion);
		}
    }else{
      personalInfoService.update(personalInfoUnion);
    }
    List<Integer> addressTypes=new ArrayList<>();
    if(param.containsKey("companyAddressId")){
      addressTypes.add(0);
    }
    if(param.containsKey("homeAddressId")){
      addressTypes.add(1);
    }
    if(param.containsKey("residenceAddressId")){
      addressTypes.add(2);
    }
    if(addressTypes.size()>0){
      for(Integer addressType:addressTypes){
        AuthPersonalAddress personalAddress=setAuthPersonalAddress(personalInfoUnion,addressType);
        savePersonalAddress(personalAddress,cust);
      }
    }
    //添加补充认证项纪录
  custSupplementItemService.itemDone(cust,productId,1,String.valueOf(personalInfoUnion.getPersonalInfoId()),null);
    if(productId !=null && productId.equals(0L)){
      custSupplementItemService.itemDone(cust,6L,1,String.valueOf(personalInfoUnion.getPersonalInfoId()),null);
      custSupplementItemService.itemDone(cust,3L,1,String.valueOf(personalInfoUnion.getPersonalInfoId()),null);
    }
  }

  /**
   * 获取基本信息联合对象
   * @param cust
   * @return
   * @throws Exception
   */
  private PersonalInfoUnion getPersonalInfoUnion(Cust cust) throws Exception{
    PersonalInfoUnion personalInfoUnion = new PersonalInfoUnion();
    AuthPersonalInfo authPersonalInfo=personalInfoService.findByProcessId(cust.getLastProccessId());
    if(authPersonalInfo!=null) {
      BeanUtils.copyProperties(personalInfoUnion,authPersonalInfo);
      List<AuthPersonalAddress> addressList = authPersonalAddressService.findByCustId(cust.getCustId(), null);
      if(addressList!=null && addressList.size()>0) {
        for (AuthPersonalAddress address : addressList) {
          String areaCode=address.getProvinceCode()+"-"+address.getCityCode()+"-"+address.getZoneCode();
          if(areaCode.length()!=20) areaCode="";
          if (address.getAddressType() == 0) {
            personalInfoUnion.setCompanyAddressId(address.getAddressId());
            personalInfoUnion.setCompanyName(address.getAddressName());
            personalInfoUnion.setCompanyTel(address.getPhone());
            personalInfoUnion.setCompanyAreaCode(areaCode);
            personalInfoUnion.setCompanyAddress(address.getAddress());
          } else if (address.getAddressType() == 1) {
            personalInfoUnion.setHomeAddressId(address.getAddressId());
            personalInfoUnion.setHomeTel(address.getPhone());
            personalInfoUnion.setHomeAreaCode(areaCode);
            personalInfoUnion.setHomeAddress(address.getAddress());
          } else if (address.getAddressType() == 2) {
            personalInfoUnion.setResidenceAddressId(address.getAddressId());
            personalInfoUnion.setResidenceTel(address.getPhone());
            personalInfoUnion.setResidenceAreaCode(areaCode);
            personalInfoUnion.setResidenceAddress(address.getAddress());
          }
        }
      }
    }
    return personalInfoUnion;
  }

  /**
   * 获取根目录
   * @param fileClassPath
   * @return
   * @throws Exception
   */
  private Element getRootElement(String fileClassPath) throws Exception{
    File cfgFile =ResourceUtils.getFile(fileClassPath);
    SAXReader saxReader = new SAXReader();
    Document document = saxReader.read(cfgFile);
    Element element=document.getRootElement();
    return element;
  }
  private PersonalInfoUnion setPersonalInfoUnion(Map<String,Object> param) throws Exception{
    PersonalInfoUnion personalInfoUnion=new PersonalInfoUnion();
    for(Map.Entry<String,Object> entry:param.entrySet()){
      String columnName=entry.getKey();
      if("location".equals(columnName)){
        if(entry.getValue()!=null && !"".equals(entry.getValue().toString())){
          Location location=new Location();
          Map<String,String> locationMap=(Map<String,String>)entry.getValue();
          location.setCityName(locationMap.get("cityName"));
          location.setDistinct(locationMap.get("distinct"));
          location.setRoad(locationMap.get("road"));
          location.setLatitude(String.valueOf(locationMap.get("latitude")));
          location.setLongitude(String.valueOf(locationMap.get("longitude")));
          location.setCityAddress(locationMap.get("cityAddress"));
          location.setIp(locationMap.get("ip"));
          personalInfoUnion.setLocation(location);
        }
      }else{
        if(entry.getValue()!=null && !"".equals(entry.getValue().toString())){
          Object value=entry.getValue();
          Class unionClass = PersonalInfoUnion.class;
          StringBuilder stringBuilder=new StringBuilder();
          stringBuilder=stringBuilder.append("set").append(columnName.substring(0, 1).toUpperCase()).append(columnName.substring(1));
          Method[] methods=unionClass.getMethods();
          for(Method method:methods){
            if(method.getName().equals(stringBuilder.toString())){
              Class[] parameterTypes=method.getParameterTypes();
              String parameterType=parameterTypes[0].getSimpleName();
              if(parameterType.equals("String")){
                method.invoke(personalInfoUnion,(String)value);
              }else if(parameterType.equals("Integer")){
                method.invoke(personalInfoUnion,Integer.valueOf(value.toString()));
              }else if(parameterType.equals("Long")){
                method.invoke(personalInfoUnion,Long.valueOf(value.toString()));
              }
            }
          }
        }
      }
    }
    return personalInfoUnion;
  }

  /**
   * 设置地址信息
   * @param personalInfoUnion
   * @param addressType
   * @return
   */
  private AuthPersonalAddress setAuthPersonalAddress(PersonalInfoUnion personalInfoUnion,Integer addressType){
    AuthPersonalAddress personalAddress=new AuthPersonalAddress();
    String areaCode="";
    if(addressType==0){
      personalAddress.setAddressId(personalInfoUnion.getCompanyAddressId());
      personalAddress.setAddressName(personalInfoUnion.getCompanyName());
      personalAddress.setAddressType(addressType);
      personalAddress.setAddress(personalInfoUnion.getCompanyAddress());
      personalAddress.setRoad(personalInfoUnion.getCompanyAddress());
      personalAddress.setPhone(personalInfoUnion.getCompanyTel());
      if(personalInfoUnion.getCompanyAreaCode()!=null){
        areaCode=personalInfoUnion.getCompanyAreaCode();
      }
    }else if(addressType==1){
      personalAddress.setAddressId(personalInfoUnion.getHomeAddressId());
      personalAddress.setAddressType(addressType);
      personalAddress.setAddress(personalInfoUnion.getHomeAddress());
      personalAddress.setRoad(personalInfoUnion.getHomeAddress());
      personalAddress.setPhone(personalInfoUnion.getHomeTel());
      if(personalInfoUnion.getHomeAreaCode()!=null){
        areaCode=personalInfoUnion.getHomeAreaCode();
      }
    }else if(addressType==2){
      personalAddress.setAddressId(personalInfoUnion.getResidenceAddressId());
      personalAddress.setAddressType(addressType);
      personalAddress.setAddress(personalInfoUnion.getResidenceAddress());
      personalAddress.setRoad(personalInfoUnion.getResidenceAddress());
      personalAddress.setPhone(personalInfoUnion.getResidenceTel());
      if(personalInfoUnion.getResidenceAreaCode()!=null){
        areaCode=personalInfoUnion.getResidenceAreaCode();
      }
    }
    String[] codes=areaCode.split("-");
    if (codes.length==3){
      SysNation province=sysNationService.findByCode(codes[0]);
      if (province!=null){
        personalAddress.setProvince(province.getProvince());
        personalAddress.setProvinceCode(province.getCode());
      }
      SysNation city=sysNationService.findByCode(codes[1]);
      if (city!=null){
        personalAddress.setCity(city.getCity());
        personalAddress.setCityCode(city.getCode());
      }
      SysNation district=sysNationService.findByCode(codes[2]);
      if (district!=null){
        personalAddress.setZone(district.getDistrict());
        personalAddress.setZoneCode(district.getCode());
      }
    }
    Location location=personalInfoUnion.getLocation();
    if(location!=null){
      personalAddress.setGeoAddress(location.getCityAddress());
      personalAddress.setGeoCity(location.getCityName());
      personalAddress.setGeoZone(location.getDistinct());
      personalAddress.setGeoLatitude(location.getLatitude());
      personalAddress.setGeoLongitude(location.getLongitude());
      personalAddress.setGeoRoad(location.getRoad());
      personalAddress.setIp(location.getIp());
    }
    return personalAddress;
  }

  /**
   * 保存地址信息
   * @param personalAddress
   * @param cust
   */
  private void savePersonalAddress(AuthPersonalAddress personalAddress,Cust cust){
    if(personalAddress.getAddressId()!=null){
      authPersonalAddressService.update(personalAddress);
    }else{
      List<AuthPersonalAddress> oldAuthPersonalAddress=authPersonalAddressService.findByCustId(cust.getCustId(),personalAddress.getAddressType());
      if(oldAuthPersonalAddress!=null && oldAuthPersonalAddress.size()>0){
        personalAddress.setAddressId(oldAuthPersonalAddress.get(0).getAddressId());
        authPersonalAddressService.update(personalAddress);
      }else{
        personalAddress.setCustId(cust.getCustId());
        personalAddress.setProcessId(cust.getLastProccessId());
        authPersonalAddressService.insert(personalAddress);
      }
    }
  }
}
